﻿using System.Text;
using FunctionalCLR.Core;

namespace Zove.Runtime {

    /// <summary>
    /// Enhanced C# trnaslator
    /// </summary>
    public class EnhancedCSharpCodeTranslator : CSharpCodeTranslator {

        private string prefix = string.Empty;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="funMgr"></param>
        /// <param name="prefix"></param>
        public EnhancedCSharpCodeTranslator(
            IFunctionManager funMgr, string prefix)
            : base(funMgr) {
            this.prefix = prefix;
        }

        /// <summary>
        /// Add prefix
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public override object Visit(IdentifierNode node) {
            return string.IsNullOrEmpty(prefix)
                ? node.Value : prefix + "." + node.Value;
        }

        /// <summary>
        /// Check if the function is a CLR built in function
        /// </summary>
        /// <param name="funcName"></param>
        /// <returns></returns>
        public static bool IsCLRShipped(string funcName) {
            string[] funcNames = new string[] {
                "abs", "sin", "cos", 
                "tan", "asin", "acos", 
                "atan", "cosh", "sinh", "tanh"};
            foreach (string f in funcNames) {
                if (f == funcName) {
                    return true;
                }
            }

            return false;
        }

        public override object Visit(FuncNode node) {
            string name = string.Empty;

            if (IsCLRShipped(node.Value)) {
                name = "Math."
                    + char.ToUpper(node.Value[0])
                    + node.Value.Substring(
                    1, node.Value.Length - 1).ToLower();
            } else {
                name = node.Value;
            }

            StringBuilder buff = new StringBuilder();

            buff.Append(name).Append("(");
            for (int index = 0; 
                index < node.Parameters.Count; index++) {
                object value = node.Parameters[index].Accept(this);
                buff.Append(value.ToString());
                if (index + 1 < node.Parameters.Count) {
                    buff.Append(",");
                }
            }
            buff.Append(")");

            return buff.ToString();
        }
    }
}
